home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / yerk / mps231ss.hqx / Mops source / More classes / MW documents / G&HFmod.txt next >
Text File  |  1992-05-07  |  13KB  |  509 lines

  1. \ This module handles graphics, headers, footers and footnotes.
  2.  
  3. \ We don't do anything terribly clever with graphics.  On input, we ignore
  4. \ them except we retain the 01 character in the text wherever a graphic occurs.
  5. \ On output, we just generate an empty default graphic wherever the text has
  6. \ an 01.
  7.  
  8. hex    
  9. table    GRAPHIC_INFO
  10.     FFFF w,  E ,  0 ,  0 w,  48 w,  48 w,
  11. end_table
  12.  
  13. table    GRAPHIC_FMT
  14.     0040 w,  0 w,  0 w,  0 w,  0300 w,  0 w,
  15. end_table
  16.  
  17. table    SPEC_FMT
  18.     0040 w,
  19. end_table
  20. decimal
  21.  
  22. : ?ALIGN_TEXT
  23.     size: text  1 and  0EXIT
  24.     pos: text  0 +: text  >pos: text  ;
  25.  
  26. : MARK_SPEC  { \ code offs -- }
  27.     pos: text  -> offs                \ Save pos: text
  28.     ?align_text  true -> GHF?
  29.     offs  false  find_posn: fmt_run  offs  new_item: fmt_run
  30.     0 >nxtc: fmt_run  $ 40 >nxtc: fmt_run
  31.     lim: text 2+  >nxtw: fmt_run
  32.     6 skip: fmt_run
  33.     $ FFFF >nxtw: fmt_run                \ Store dummy font #
  34.     1st: text 1-  dup -> code  >nxtc: fmt_run    \ And code #
  35.     1 skip: fmt_run
  36.     code  NIF  graphic_info  add: text  THEN
  37.     offs  >pos: text  ;                \ Restore  pos: text
  38.  
  39.  
  40. : MARK_SP        \ Exported.  Called on output, after FIXUP_HFS.
  41.     text_only?  ?EXIT
  42.     reset: text  reset: fmt_run
  43.     1 4 selRange: utTbl
  44.     BEGIN
  45.         text&hf_len >lim: text
  46.         utTbl  scan: text  0EXIT
  47.         step: text  mark_spec  1 skip: text
  48.     AGAIN  ;
  49.  
  50.  
  51. \    ==== Sections, headers and footers and footnotes ====
  52.  
  53. false    value    1st_SPECIAL?
  54.     0    value    HF_FLGS
  55.     0    value    HF_OFFS
  56.     0    value    HF_STRT
  57.     0    value    HF_POS
  58.     0    value    HF_LIM
  59.     0    value    HF_CODE
  60.     0    value    HF_DISPL
  61.     0    value    SECT_OFFS_POS
  62.     0    value    SECT_DESC_POS
  63.     0    value    FTN_OFFS_POS
  64.  
  65. hex
  66. table    SECT_INDIC
  67.     0241 w, 00 c,
  68. \    0208 w, 00 c,                \ 4
  69. \    0E3C w, 02E1 w, 3D06 w, A541 w, 0044 w, 02E1 w, 4502 w, E1 c,
  70. end_table
  71.  
  72. table    SECT_INDIC+1st_SPEC
  73. \    04370141 , 00 c,            \ 4 ****EXPERIMENTING
  74. \    0208 w, 00 c,
  75.     0A37 w, 013c w, 02e1 w, 3d06 w, a541 w, 00 c,
  76.  
  77. \ It seems with Word 4 opening a Word 3 document, we need all this stuff!!
  78.  
  79. end_table
  80.  
  81. table  HF_STYLES
  82.     F4F4F3F3 , F4F3 w,
  83. end_table
  84.  
  85. table    HF_MASKS
  86.     01020408 , 1020 w,
  87. end_table
  88. decimal
  89.  
  90. scon    2RETS    "RR"    & R  RET  instead
  91. scon    4RETS    "RRRR"    & R  RET  instead
  92.  
  93.  
  94. \        ========== Utility words ===========
  95.  
  96. : SELHFS
  97.     clear: utTbl  $ 10 $ 15  selRange: utTbl  ;
  98.  
  99. : INSERT_MK    \ ( c -- )  Inserts the given mark in text.
  100.         \ pos: text marks the spot.
  101.     pos: text dup  0 1  fixup: fmt_run  0 1  fixup: para_run
  102.     1 ++> text&hf_len  1 ++> HF_displ
  103.     pos: text  real_text_len <  --> real_text_len
  104.     1 ++> #insrtd
  105.     chinsert: text  ;
  106.  
  107. : REMOVE_MK
  108.     pos: text  dup  1 0  fixup: fmt_run  1 0 fixup: para_run
  109.     1 deleten: text  -1 ++> text&hf_len  -1 ++> #insrtd  ;
  110.  
  111.  
  112. \        ============ Input ============
  113.  
  114. \ SPEC_IN (exported) is called when a "special" format is detected.
  115.  
  116. : SPEC_IN  { offs -- }
  117.     fmt c@  $ C  >=  ?EXIT        \ Out if it's a graphic
  118. \    unmpd_old  >pos: theFile
  119. \    unmpd_new  >lim: theFile
  120. \    theFile ->: sect_str  \ *** may not need this - see next word.
  121. ;
  122.  
  123. : GET_HF_FLGS
  124.     sect_desc_pos  >pos: sect_offsets
  125.     len: sect_offsets  6 <  IF  0 -> HF_flgs  EXIT  THEN
  126.     theFile  copyto: sect_str
  127.     2 skip: sect_offsets
  128.     4 nxtN: sect_offsets
  129.     6 ++> sect_desc_pos
  130.     dup  0<  IF  drop  EXIT  THEN            \ 4
  131.     hdr_len -  ( #insrtd + )  >pos: sect_str    \ ***chk OK
  132.     len: sect_ov_str
  133.     IF
  134.         sect_offs_pos  >pos: sect_offsets  4 ++> sect_offs_pos
  135.         nxtL: sect_offsets
  136.             sect_desc_pos  >pos: sect_offsets
  137.         ^1st: sect_ov_str @ 1+  =
  138.         IF  ( use override value )
  139.             4 skip: sect_ov_str
  140.             nxtW: sect_ov_str  -> HF_flgs  EXIT
  141.         THEN
  142.     THEN
  143.     count: sect_str        \ Info for this section
  144.     mw4?
  145.     IF  $ 80  ELSE  $ 41  THEN
  146.     chsearch: sect_str
  147.     NIF    0
  148.     ELSE    2 more: sect_str  last: sect_str 
  149.     THEN  -> HF_flgs  ;
  150.  
  151. : MK_HF        \ ( n -- )
  152.     ( n )  $ 10  or  ^1st: text  c!  ;
  153.         \ That had better have been a RET we wiped out!
  154.  
  155. : >NXTHF
  156.     len: theFile
  157.     IF    4 nxtN: theFile  HF_strt +  HF_displ +
  158.     ELSE    text&HF_len
  159.     THEN
  160.     1- >pos: text  nolim: text  ;
  161.  
  162. : MARK_HFS_FOR_SECT
  163.     get_HF_flgs  HF_flgs
  164.     IF
  165.         6 0 DO
  166.             HF_masks drop  i +  c@
  167.             HF_flgs and  IF  i mk_HF  >nxtHF  THEN
  168.         LOOP
  169.     THEN
  170.     sect_end_mark insert_mk  ;
  171.  
  172.  
  173. : SETUP_SECT_OFFS    \ Skips the offsets to the section markers in the
  174.             \ text, and gets us to the offsets into the
  175.             \ section info.
  176.     reset: sect_ov_str
  177.     4 len: sect_offsets  min  -> sect_offs_pos
  178.     BEGIN
  179.         len: sect_offsets  4 <  ?EXIT
  180.         4 nxtN: sect_offsets  text&hf_len  #insrtd -  >=
  181.     UNTIL
  182.     pos: sect_offsets  -> sect_desc_pos  ;
  183.  
  184.  
  185. : MARK_FTN    \ Exported.
  186.     reset: fmt_run  reset: para_run  reset: ftn_markers  reset: text
  187.     ftn_mark  ^1st: text  real_text_len +  ftn_len +  2-  c!
  188.             \ That should have been a RET we wiped out!
  189.     BEGIN
  190.         len: ftn_markers  8 <=  ?EXIT
  191.         nxtL: ftn_markers  #insrtd +  >pos: text
  192.         ftn_mark  insert_mk
  193.         nxtL: ftn_offsets  real_text_len + 1-  >pos: text
  194.         ftn_mark  ^1st: text  c!    \ Should have been a RET!
  195.     AGAIN  ;
  196.  
  197.  
  198. : MARK_HFS        \ Exported.  Called last.
  199.     real_text_len  1- >pos: text  nolim: text
  200.     reset: fmt_run  reset: para_run        \ For insert_mk following
  201.     text_end_mark  insert_mk        \ Comes before final RET
  202.     0 -> hf_displ  pos: text 1+  -> HF_strt
  203.     setup_sect_offs
  204.     >nxtHF
  205.     BEGIN
  206.         len: sect_offsets
  207.     WHILE
  208.         mark_HFs_for_sect
  209.     REPEAT  ;
  210.  
  211.  
  212. \        =========== Output ============
  213.  
  214.   0    value    HF_CNT
  215.  
  216. : ADD_SECT_INFO
  217.     HF_flgs dup +: src    \ Leave flags in src for SECT_STR_OUT
  218.     0EXIT
  219.     HF_flgs  $ F >        \ Is there a "1st" hdr/ftr?
  220.     IF  sect_indic+1st_spec  ELSE  sect_indic  THEN
  221.     add: tmp
  222.     HF_flgs  ^1st: tmp  1-  c!  ;
  223.  
  224.  
  225. : (HFS_FOR_SECT)  { \ hf# -- }
  226.     0 -> HF_flgs
  227.     len: text  0EXIT        \ Out if no hdrs/ftrs for this sect
  228.     lim: text  ( save - used in loop below )
  229.     BEGIN
  230.         1st: text  $ 10 -  -> hf#
  231.         HF_masks drop  hf# +  c@
  232.         HF_flgs or  -> HF_flgs
  233.         RET  >nxtc: text
  234.         pos: text  real_text_len -  +L: HF_offsets
  235.         pos: text  new_item: para_run
  236.         hf_styles drop  hf# + c@    \ hdr or ftr style#
  237.         ^1st: para_run  w!  skip_info: para_run
  238.         utTbl scan: text
  239.       \ Now we ensure that this HF ends with RET - WordFormat could have
  240.       \ wiped it out!
  241.         len: text  ( just in case )
  242.         IF   RET  ^1st: text  len: text + 1-  c!   THEN
  243.         step: text
  244.         over >lim: text
  245.     NUNTIL
  246.     drop  ;
  247.  
  248.  
  249. : S+HF  { \ len #left -- offs }
  250.     1st: tmp 1+  -> len        \ Length of next item
  251.     $ 80  lim: text $ 7F and -  -> #left
  252.                     \ # bytes left in text block
  253.     len #left >
  254.     IF                \ Not enough room - go to next block
  255.         pad #left  add: text
  256.     THEN
  257.     pos: text  hdr_len +        \ Return result
  258.     len >len: tmp  tmp  $add: text
  259.     step: tmp  ;
  260.  
  261. : SECT_STR_OUT
  262.     reset: tmp  reset: src  end: text
  263.     BEGIN
  264.         len: src  0EXIT
  265.         nxtc: src        \ HF flags for next section
  266.         IF    S+HF        \ Section has hdrs/footers
  267.         ELSE    -1
  268.         THEN
  269.         3 +W: sect_offsets  +L: sect_offsets
  270.     AGAIN  ;
  271.  
  272. \ : HF_SETUP
  273. \    11 need_level            \ It appears that Word supplies
  274. \    start: style_names        \ this stuff if we don't put it in.
  275. \    pad 3  2dup erase  insert: style_names
  276. \    3 ++> #levels  ;        \ But we'll keep the code here ready 
  277.                     \ just in case.
  278.  
  279. : HF_WINDUP
  280.     real_text_len text&hf_len =  ?EXIT
  281.     BEGIN
  282.         end: text  -4 skip: text  4RETS =?: text
  283.     NWHILE
  284.         RET  +: text
  285.     REPEAT
  286.     lim: text  real_text_len -  2-
  287.     dup  +L: HF_offsets  1+  +L: HF_offsets
  288.     lim: text  -> text&hf_len  ;
  289.  
  290. : FIX_HFS_FOR_SECT
  291.     save: text
  292.     HF_pos  >pos: text  nolim: text
  293.     sect_end_mark  chsearch: text
  294.     IF  pos: text  step: text  remove_mk  <step: text  >pos: text  THEN
  295.     pos: text  false  find_posn: para_run
  296.     (HFs_for_sect)
  297. ( NOTE: may need to chk for RETs at end of text here )
  298.     step: text
  299.     pos: text dup false find_posn: para_run  new_item: para_run
  300.                     \ Leave style# zero for Normal
  301.     skip_info: para_run
  302.     pos: text  -> HF_pos        \ Remember where we're up to
  303.     restore: text
  304.     add_sect_info  ;
  305.  
  306.  
  307. : HFS_FOR_SECTS        \ lim: text points to the first sect marker in text,
  308.             \ or to the end of the text proper.
  309.     0  +L: sect_offsets
  310.     selHFs
  311.     BEGIN
  312.         step: text  real_text_len 1-  >lim: text
  313.         fix_HFs_for_sect
  314.         len: text  0<=  ?EXIT
  315.         1 skip: text  pos: text  +L: sect_offsets
  316.         SECT chsearch: text  drop
  317.     AGAIN  ;
  318.  
  319.  
  320. : TEXT_END_FMT    \ Sets up a dummy fmt_run entry for the end of the text,
  321.         \ unless there's one there already.
  322.  
  323.     real_text_len  true  find_posn: fmt_run
  324.     pos: fmt_run
  325.     IF
  326.         ^1st: fmt_run  itemsize: fmt_run -  @  real_text_len =  ?EXIT
  327.     THEN
  328.   \ OK, do it
  329.     real_text_len  new_item: fmt_run
  330.     pad  infoSize: fmt_run  2dup  $ 80  fill
  331.     >nxt$: fmt_run  ;
  332.  
  333.  
  334. : FIXUP_HFS    \ Exported.  This is called after UPDATE_HFS, but before
  335.         \ we have output anything.
  336.         \ It fixes up the section and header/footer info, if
  337.         \ there is any, then calls text_end_fmt.  This has to be
  338.         \ done last, so that any transformations don't move the
  339.         \ entry away from real_text_len.  Word bombs if it isn't
  340.         \ right there!!
  341.  
  342.     reset: text  reset: para_run
  343.     start: text  real_text_len 1-
  344.     dup  >lim: text  dup -> HF_pos -> HF_lim
  345.     SECT chsearch: text
  346.     GHF? or  dup  -> GHF?
  347.     NIF  \ No headers, footers or sections - get out
  348.         text_end_fmt  EXIT
  349.     THEN
  350.     0 -> hf_offs  new: tmp  new: src
  351.     HFs_for_sects
  352.     hf_windup
  353.     text&hf_len  +L: sect_offsets
  354.     sect_str_out  release: tmp  release: src
  355.     trim_fmt_run  trim_para_run
  356.     text_end_fmt  ;
  357.  
  358.  
  359. : HANDLE_SPEC  { \ code -- offs addr len }  \ Exported.  Called when
  360.         \ SET_FMT: detects a "special" format.
  361.  
  362.     ^1st: fmt_run 12 + c@  -> code   code
  363.     NIF  ( graphic )
  364.         ^1st: fmt_run 2+ w@  ( offset )  hdr_len +
  365.         graphic_fmt + 2- w!
  366.         save_offs 1+  graphic_fmt
  367.     ELSE  ( section or other info )
  368.         save_offs
  369.         code 1 3 within? nip -    \ Add 1 if date, time or page# code
  370.         spec_fmt
  371.     THEN  ;
  372.  
  373. : GHF_FORMATS_OUT    \ Exported.  Called to output the final formats
  374.             \ if GHF? is true.
  375.     text&hf_len  real_text_len  =
  376.     NIF  text&hf_len  pad 0  str_out  THEN
  377.     total_text_len  text&hf_len  =
  378.     NIF  total_text_len  spec_fmt  str_out  THEN  ;
  379.  
  380.  
  381. \        ======= Moving H/F text before output ========
  382.  
  383. : REMOVE_HF
  384.     1 skip: text  utTbl scan: text  drop  -1 skip: text
  385.     pos: text  len: text  2dup
  386.     0  fixup: fmt_run  0  fixup: para_run
  387.     len: text negate  dup  ++> HF_lim  ++> text&hf_len
  388.     delete: text  ;
  389.  
  390. : FIND_HF_PLACE
  391.     HF_pos >pos: text
  392.     BEGIN
  393.         HF_lim >lim: text
  394.         utTbl scan: text  step: text  0EXIT
  395.         1st: text  HF_code  2dup  >  IF  2drop  EXIT  THEN
  396.         = IF  remove_HF  EXIT  THEN
  397.         1 skip: text
  398.     AGAIN  ;
  399.  
  400. : MOVE_HF  { \ hfpos -- }
  401.     save: text  find_HF_place  pos: text -> hfpos
  402.     restore: text
  403.     pos: text  len: text  2dup
  404.     hfpos  move: fmt_run  hfpos  move: para_run
  405.     text ->: tmp
  406.     RET  ptr: tmp  lim: tmp +  1-  c!
  407.     pos: text            \ Save
  408.     len: text  negate
  409.     dup ++> hfpos  dup ++> hf_pos  ++> real_text_len \ Adjust for deletion
  410.     delete: text
  411.     hfpos >pos: text  nolim: text
  412.     reset: tmp  tmp $insert: text
  413.     >pos: text  ;            \ Restore
  414.  
  415.  
  416. : NEXT_SECT
  417.     save: text  HF_lim  >pos: text  nolim: text
  418.     HF_cnt        \ We don't skip anything first time in!!
  419.     IF
  420.         sect_end_mark  1st: text =  IF  1 skip: text  THEN
  421.     THEN
  422.     pos: text  -> HF_pos
  423.     sect_end_mark  chsearch: text
  424.     NIF
  425.         sect_end_mark chinsert: text  1 ++> text&hf_len
  426.         pos: text 1-
  427.     ELSE
  428.         lim: text
  429.     THEN
  430.     -> HF_lim
  431.     restore: text  ;
  432.     
  433. : HFITEM
  434.     HF_cnt        \ If 1st time in, delimit 1st sect in h/f area
  435.     NIF  next_sect  THEN
  436.     true -> GHF?
  437.     step: text  real_text_len 1-  >lim: text
  438.     1st: text  SECT =
  439.     IF
  440.         next_sect  1 skip: text
  441.     ELSE
  442.         1st: text  -> HF_code  $ 16  chsearch: text
  443.         IF  1 more: text  THEN
  444.         move_HF
  445.     THEN  ;
  446.  
  447.  
  448. : MARK_TEXT_END
  449.     reset: text  len: text  -> text&hf_len
  450.     text_end_mark  chsearch: text  step: text
  451.     IF  remove_mk  THEN
  452.     len: text
  453.     NIF            \ It's straight text, no hdrs/ftrs.
  454.         start: text  last: text  RET <>
  455.         IF
  456.             RET  +: text  start: text
  457.         THEN
  458.         lim: text  dup  -> real_text_len  -> text&hf_len
  459.  
  460.     ELSE        \ pos: text points to the char where the
  461.             \ final RET will go.
  462.  
  463.         pos: text 1+  -> real_text_len  true -> GHF?
  464.     THEN
  465.     reset: text  reset: fmt_run  ;
  466.  
  467.  
  468. : FIXUP_FTN
  469.     ftn_len  0EXIT            \ Do nothing if no footnotes
  470.                     \ were input.  Maybe change later.
  471.     reset: fmt_run  reset: para_run        \ For remove_mk calls
  472.     start: text  real_text_len  -> ftn_offs_pos
  473.     BEGIN
  474.         real_text_len 1-  >lim: text
  475.         ftn_mark  chsearch: text
  476.     WHILE
  477.         step: text  remove_mk  -1 ++> real_text_len
  478.         pos: text  +L: ftn_markers
  479.     REPEAT
  480.     step: text
  481.     lim: text 1-  +L: ftn_markers  0 +L: ftn_markers
  482.     BEGIN
  483.         ftn_mark  chsearch: text
  484.     WHILE
  485.         step: text  RET  ^1st: text  c!
  486.         pos: text  real_text_len - 1+  +L: ftn_offsets
  487.     REPEAT
  488.     lim: text  real_text_len -  dup  +L: ftn_offsets
  489.     2-  -> ftn_len  ;
  490.  
  491.  
  492. \ UPDATE_HFS (exported) removes any header/footer strings from TEXT, and 
  493. \ puts them in the appropriate place in the HF area at the end of the text.
  494.  
  495. : UPDATE_HFS  { \ cnt -- }
  496.     reset: fmt_run  reset: para_run  0 -> cnt  0 -> HF_cnt
  497.     new: tmp  mark_text_end
  498.     real_text_len 1-  -> HF_lim
  499.     selHFs                    \ Select hdr/ftr codes
  500.     SECT  selChar: utTbl            \ and SECT mark
  501.     start: text
  502.     BEGIN
  503.         real_text_len 1-  >lim: text
  504.         utTbl  scan: text        \ Any more of that lot?
  505.     WHILE
  506.         HFitem  1 ++> HF_cnt
  507.     REPEAT
  508.     release: tmp  ;
  509.